// Package bootstrap /*
/*
 * @Author: lineCode 1145938682@qq.com
 * @Date: 2025-06-26 15:22:32
 * @LastEditors: lineCode 1145938682@qq.com
 * @LastEditTime: 2025-06-28 16:29:52
 * @FilePath: /backend/shorthand-go/bootstrap/bootstrap.go
 */
package bootstrap

import (
	"fmt"
	"shorthand-go/dao/resource"
	"shorthand-go/httpServer"

	"github.com/gin-gonic/gin"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/nacos_client"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/nacos-group/nacos-sdk-go/v2/common/http_agent"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
	"go.uber.org/zap"
	"gopkg.in/yaml.v3"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func MustInit(confByte []byte) error {
	err := yaml.Unmarshal(confByte, &resource.AppConfig)
	if err != nil {
		return fmt.Errorf("解析配置文件失败: %v", err)
	}

	// 初始化日志
	if err := initLog(); err != nil {
		resource.Logger.Fatal("初始化日志失败", zap.Error(err))
	}
	defer func(Logger *zap.Logger) {
		if err := Logger.Sync(); err != nil {
			resource.Logger.Fatal("日志同步失败", zap.Error(err))
		}
	}(resource.Logger)

	// 初始化MySQL
	if err := initDB(); err != nil {
		resource.Logger.Fatal("初始化数据库失败", zap.Error(err))
	}

	// 初始化Nacos
	if err := initNacos(); err != nil {
		resource.Logger.Fatal("初始化Nacos失败", zap.Error(err))
	}

	// 初始化Gin
	if err := initGin(); err != nil {
		resource.Logger.Fatal("初始化Gin失败", zap.Error(err))
	}

	return nil
}

// 初始化日志
func initLog() error {
	zapConfig := zap.NewProductionConfig()
	zapConfig.OutputPaths = []string{resource.AppConfig.Log.Filename, "stdout"}

	level, err := zap.ParseAtomicLevel(resource.AppConfig.Log.Level)
	if err != nil {
		return fmt.Errorf("解析日志级别失败: %v", err)
	}
	zapConfig.Level = level

	resource.Logger, err = zapConfig.Build()
	if err != nil {

		return fmt.Errorf("初始化日志失败: %v", err)
	}

	zap.ReplaceGlobals(resource.Logger)
	return nil
}

// 初始化MySQL数据库连接
func initDB() error {
	var err error
	resource.MysqlClient, err = gorm.Open(mysql.Open(resource.AppConfig.Mysql.DSN))
	if err != nil {
		return fmt.Errorf("数据库连接失败: %v", err)
	}

	// 设置连接池
	sqlDB, err := resource.MysqlClient.DB()
	if err != nil {
		return err
	}
	sqlDB.SetMaxIdleConns(resource.AppConfig.Mysql.MaxIdleConns)
	sqlDB.SetMaxOpenConns(resource.AppConfig.Mysql.MaxOpenConns)

	resource.Logger.Info("MySQL数据库连接成功")
	return nil
}

// 初始化Nacos配置
func initNacos() error {

	// 创建Nacos配置
	serverConfigs := []constant.ServerConfig{
		{IpAddr: resource.AppConfig.Nacos.ServerAddr, Port: 8848},
	}

	clientConfig := constant.ClientConfig{
		NamespaceId:         resource.AppConfig.Nacos.Namespace,
		TimeoutMs:           uint64(resource.AppConfig.Nacos.Timeout),
		NotLoadCacheAtStart: false, // 修改为false允许加载缓存
		Username:            resource.AppConfig.Nacos.Username,
		Password:            resource.AppConfig.Nacos.Password,
		LogDir:              resource.AppConfig.Nacos.LogDir,
	}

	// 添加配置验证
	if resource.AppConfig.Nacos.ServerAddr == "" || resource.AppConfig.Nacos.DataID == "" || resource.AppConfig.Nacos.Group == "" {
		return fmt.Errorf("nacos配置不完整: server_addr=%s, data_id=%s, group=%s",
			resource.AppConfig.Nacos.ServerAddr, resource.AppConfig.Nacos.DataID, resource.AppConfig.Nacos.Group)
	}

	// 创建配置客户端
	nc := nacos_client.NacosClient{}
	_ = nc.SetServerConfig(serverConfigs)
	_ = nc.SetClientConfig(clientConfig)
	_ = nc.SetHttpAgent(&http_agent.HttpAgent{})
	client, err := config_client.NewConfigClient(&nc)
	if err != nil {
		return fmt.Errorf("创建Nacos客户端失败: %v", err)
	}

	// 获取配置并添加详细错误日志
	content, err := client.GetConfig(vo.ConfigParam{
		DataId: resource.AppConfig.Nacos.DataID,
		Group:  resource.AppConfig.Nacos.Group,
	})
	if err != nil {
		return fmt.Errorf("获取Nacos配置失败: 数据ID=%s, 分组=%s, 错误=%v", resource.AppConfig.Nacos.DataID, resource.AppConfig.Nacos.Group, err)
	}

	if err := yaml.Unmarshal([]byte(content), &resource.NacosConfig); err != nil {
		return fmt.Errorf("解析YAML失败: %w", err)
	}

	resource.Logger.Info("成功从Nacos获取配置，结构化数据", zap.Any("content", resource.NacosConfig))

	return nil
}

// 初始化Gin
func initGin() error {
	router := gin.Default()

	// 初始化路由
	httpServer.RouterInit(router)

	// 启动服务
	resource.Logger.Info(fmt.Sprintf("服务启动成功，监听端口: %d", resource.AppConfig.App.Port))
	if err := router.Run(fmt.Sprintf(":%d", resource.AppConfig.App.Port)); err != nil {
		resource.Logger.Fatal("服务启动失败", zap.Error(err))
	}
	return nil
}
